/**
 * The Vector3d class - Mootools version
 * Original by Robert Penner
 */

var Vector3d = new Class({
	initialize: function(x,y,z) {
		this.x = x;
		this.y = y;
		this.z = z;
	},
	toString: function() {
		var x = Math.round(this.x*1000)/1000;
		var y = Math.round(this.y*1000)/1000;
		var z = Math.round(this.z*1000)/1000;
		return '['+x+', '+y+', '+z+']';
	},
	reset: function(x,y,z) {
		this.initialize(x,y,z);
	},
	getClone: function() {
		return new Vector3d(this.x,this.y,this.z);
	},
	equals: function(v) {
		return (this.x==v.x && this.y==v.y && this.z==v.z);
	},
	plus: function(v) {
		this.x += v.x;
		this.y += v.y;
		this.z += v.z;
	},
	plusNew: function(v) {
		return new Vector3d(this.x+v.x, this.y+v.y, this.z+v.z);
	},
	minus: function(v) {
		this.x -= v.x;
		this.y -= v.y;
		this.z -= v.z;
	},
	minusNew: function(v) {
		return new Vector3d(this.x-v.x, this.y-v.y, this.z-v.z);
	},
	negate: function() {
		this.x = -this.x;
		this.y = -this.y;
		this.z = -this.z;
	},
	negateNew: function() {
		return new Vector3d(-this.x, -this.y, -this.z);
	},
	scale: function(s) {
		this.x *= s;
		this.y *= s;
		this.z *= s;
	},
	scaleNew: function(s) {
		return new Vector3d(this.x*s, this.y*s, this.z*s);
	},
	getLength: function() {
		return Math.sqrt(this.x*this.x + this.y*this.y + this.z*this.z);
	},
	setLength: function(l) {
		var r = this.getLength();
		if (r) this.scale(l/r);
		else this.x = l;
	},
	dot: function(v) {
		return this.x*v.x + this.y*v.y + this.z*v.z;
	},
	cross: function(v) {
		var cx = this.y*v.z - this.z*v.y;
		var cy = this.z*v.x - this.x*v.z;
		var cz = this.x*v.y - this.y*v.x;
		return new Vector3d(cx,cy,cz);
	},
	angleBetween: function(v) {
		var dp = this.dot(v);
		var cos = dp/(this.getLength()*v.getLength());
		return acosD(cos);
	},
	getPerspective: function(dist) {
		if (dist==undefined) dist = 300;
		return dist/(this.z+dist);
	},
	persProject: function(p) {
		if (p==undefined) p = this.getPerspective();
		this.x *= p;
		this.y *= p;
		this.z = 0;
	},
	persProjectNew: function(p) {
		if (p==undefined) p = this.getPerspective();
		return new Vector3d(p*this.x, p*this.y, 0);
	},
	rotateX: function(angle) {
		var ca = cosD(angle);
		var sa = sinD(angle);

		var tempY = this.y*ca - this.z*sa;
		var tempZ = this.y*sa + this.z*ca;
		this.y = tempY;
		this.z = tempZ;
	},
	rotateXTrig: function(ca, sa) {
		var tempY = this.y*ca - this.z*sa;
		var tempZ = this.y*sa + this.z*ca;
		this.y = tempY;
		this.z = tempZ;
	},
	rotateY: function(angle) {
		var ca = cosD(angle);
		var sa = sinD(angle);

		var tempX = this.x*ca + this.z*sa;
		var tempZ = this.x*-sa + this.z*ca;
		this.x = tempX;
		this.z = tempZ;
	},
	rotateYTrig: function(ca, sa) {
		var tempX = this.x*ca + this.z*sa;
		var tempZ = this.x*-sa + this.z*ca;
		this.x = tempX;
		this.z = tempZ;
	},
	rotateZ: function(angle) {
		var ca = cosD(angle);
		var sa = sinD(angle);

		var tempX = this.x*ca - this.y*sa;
		var tempY = this.x*sa + this.z*ca;
		this.x = tempX;
		this.y = tempY;
	},
	rotateZTrig: function(ca, sa) {
		var tempX = this.x*ca - this.y*sa;
		var tempY = this.x*sa + this.z*ca;
		this.x = tempX;
		this.y = tempY;
	},
	rotateXY: function(a, b) {
		var ca = cosD(a), sa = sinD(a);
		var cb = cosD(b), sb = sinD(b);

		var rz = this.y*sa + this.z*ca;
		this.y = this.y*ca - this.z*sa;
		this.z = this.x*-sb + rz*cb;
		this.x = this.x*cb + rz*sb;
	},
	rotateXYTrig: function(ca, sa, cb, sb) {
		var rz = this.y*sa + this.z*ca;
		this.y = this.y*ca - this.z*sa;
		this.z = this.x*-sb + rz*cb;
		this.x = this.x*cb + rz*sb;
	},
	rotateXYZ: function(a, b, c) {
		var ca = cosD(a), sa = sinD(a);
		var cb = cosD(b), sb = sinD(b);
		var cc = cosD(c), sc = sinD(c);

		var ry = this.y*ca - this.z*sa;
		var rz = this.y*sa + this.z*ca;
		var rx = this.x*cb + rz*sb;
		this.z = this.x*-sb + rz*cb;
		this.x = rx*cc - ry*sc;
		this.y = rx*sc + ry*cc;
	},
	rotateXYZTrig: function(ca, sa, cb, sb, cc, sc) {
		var ry = this.y*ca - this.z*sa;
		var rz = this.y*sa + this.z*ca;
		var rx = this.x*cb + rz*sb;
		this.z = this.x*-sb + rz*cb;
		this.x = rx*cc - ry*sc;
		this.y = rx*sc + ry*cc;
	}
});
function $v3(a,b,c) { return new Vector3d(a,b,c); }
